<?php

declare(strict_types=1);

namespace App\Controller;

use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\DbConnection\Db;
use Hyperf\Context\ApplicationContext;
use Throwable;
use App\Service\NormalOrderQueueService;
use App\Service\SpikeOrderQueueService;
use App\Service\NormalRollBackQueueService;
use App\Service\SpikeRollBackQueueService;
use App\Service\NormalBuyQueueService;
use App\Service\SpikeBuyQueueService;
use Hyperf\Di\Annotation\Inject;
use App\Controller\BaseController;
use App\Model\User;
use App\Model\Cart;
use App\Model\Product;

#[AutoController]
class ShopController extends BaseController
{
	protected $redis;

	#[Inject]
	protected NormalOrderQueueService $normalOrder;
	#[Inject]
	protected NormalRollBackQueueService $normalRollBack;
	#[Inject]
	protected SpikeOrderQueueService $spikeOrder;
	#[Inject]
	protected SpikeRollBackQueueService $spikeRollBack;
	#[Inject]
	protected NormalBuyQueueService $normalBuy;
	#[Inject]
	protected SpikeBuyQueueService $spikeBuy;

	public function __construct()
	{
		$container = ApplicationContext::getContainer();
		$this->redis = $container->get(\Hyperf\Redis\Redis::class);
	}

	public function index()
	{
		return "Hello World Shop";
	}

	//加入购物车
	public function addCart(RequestInterface $request)
	{
		$userId = $request->input('userId');
		$cartData = $request->input('cartData');

		if (!$userId || !$cartData) {
			$data['err'] = 1;
			$data['msg'] = '参数错误，重新登录';
		}

		$isAuth = $this->Auth($request, 0);
		$AuthInfo = json_decode($isAuth, true);
		if ($AuthInfo['err'] === 0) {
			// $cartList = Cart::query()->where("user_id",$userId)->get();
			// if(!empty($cartList)){
			// 	$cartArr = [];
			// 	foreach($cartList as $k => $v){
			// 		array_push($cartArr, $v['id']);
			// 	}
			// 	if(!empty($cartArr)){
			// 		Cart::destroy($cartArr);
			// 	}
			// }
			$cartList = Db::table('cart')->where('user_id', $userId)->delete();

			$cartData = json_decode($cartData, true);
			if (!empty($cartData)) {
				foreach ($cartData as $k => $v) {
					$cart = new Cart();
					$cart->user_id = $userId;
					$cart->goods_id = $v['productId'];
					$cart->num = $v['buyNum'];
					$cart->selected = $v['selected'];
					$cart->created_at = date('Y-m-d H:i:s', time());
					$cart->updated_at = date('Y-m-d H:i:s', time());
					$cart->save();
				}
			}

			$data['err'] = 0;
			$data['msg'] = '更新购物车成功';
		} else {
			$data['err'] = 1;
			$data['msg'] = '认证失败，重新登录';
		}

		return json_encode($data);
	}

	//获取订单详情
	public function getOrderdetail(RequestInterface $request)
	{
		$productArr = $request->input('productArr');
		$is_sale = $request->input('is_sale');
		if (!$productArr || !$is_sale) {
			$data['err'] = 1;
			$data['msg'] = '参数错误，重新登录';
		}

		$isAuth = $this->Auth($request, 0);
		$AuthInfo = json_decode($isAuth, true);
		if ($AuthInfo['err'] === 0) {
			$productList = [];
			if ($is_sale) {
				$cate = 'product:spike:';
			} else {
				$cate = 'product:normal:';
			}

			if (empty($productArr)) {
				$data['err'] = 1;
				$data['msg'] = '订单数据为空';
				$data['productList'] = [];
				return json_encode($data);
			}
			$productArr = str_replace("'", '"', $productArr);
			$productArr = json_decode($productArr);
			foreach ($productArr as $k => $v) {
				$productInfo = $this->redis->hgetall($cate . $v);
				if (!$productInfo) {
					$data['err'] = 1;
					$data['msg'] = '获取订单详情失败';
					$data['productList'] = [];
					return json_encode($data);
				}
				array_push($productList, $productInfo);
			}
			$data['err'] = 0;
			$data['msg'] = '获取订单详情成功';
			$data['productList'] = $productList;
		} else {
			$data['err'] = 1;
			$data['msg'] = '认证失败，重新登录';
			$data['productList'] = [];
		}
		return json_encode($data);
	}

	//获取购物车
	public function getCart(RequestInterface $request)
	{
		$userId = $request->input('userId');
		if (empty($userId)) {
			$data['err'] = 1;
			$data['msg'] = '参数错误，重新登录';
		}

		$isAuth = $this->Auth($request, 0);
		$AuthInfo = json_decode($isAuth, true);
		if ($AuthInfo['err'] === 0) {
			$cartList = Cart::query()->where('user_id', $userId)->get();
			foreach ($cartList as $k => $v) {
				$productInfo = Product::query()->where("id",$v->goods_id)->first();
				if ($productInfo) {
					$cartList[$k]->name = $productInfo->name;
					$cartList[$k]->price = $productInfo->price;
				} else {
					unset($cartList[$k]);
				}
			}
			$data['err'] = 0;
			$data['msg'] = '获取成功';
			$data['cartList'] = $cartList;
		} else {
			$data['err'] = 1;
			$data['msg'] = '认证失败，重新登录';
		}
		return json_encode($data);
	}

	//购买普通商品（分布式锁）
	public function buyNormal(RequestInterface $request)
	{
		$userid = $request->input('userid');
		$shopDataJson = $request->input('shopData');
		if (empty($userid)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$isAuth = $this->Auth($request, 1);
		$AuthInfo = json_decode($isAuth, true);
		if ($AuthInfo['err'] !== 0) {
			return json_encode(['err' => 1, 'msg' => '认证失败，重新登录']);
		}

		$token = $AuthInfo['token'];
		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$oldNum = [];   //各商品的购买数量

		Db::beginTransaction();
		try {
			$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
			if (empty($userInfo)) {
				throw new \Exception('用户不存在');
			}

			$priceAll = 0;  //订单总价格
			$orderGoods = []; //订单的商品数组
			foreach ($shopData as $k => $v) {
				$lockKey = 'product_lock:' . $v['product_id'];
				$lockExpire = 5000; // 锁的过期时间，单位毫秒
				$lockAcquired = $this->redis->set($lockKey, 1, ['NX', 'PX' => $lockExpire]);
				if (!$lockAcquired) {
					throw new \Exception('抢购失败，商品id.' . $v['product_id'] . '，为请稍后重试');
				}

				try {
					$isExists = $this->redis->exists('product:normal:' . $v['product_id']);
					if (!$isExists) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在');
					}

					$productInfo = $this->redis->hgetall('product:normal:' . $v['product_id']);
					if (empty($productInfo)) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在了');
					}

					if ($productInfo['is_sale']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '为抢购商品');
					}

					$v['num'] = intval($v['num']);
					if ($v['num'] <= 0) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '数量不大于0');
					}

					if ($productInfo['num'] < $v['num']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，数量不足');
					}

					// 监视商品，如果watch中的值被改变，事务就会终止并回滚
					$productKey = 'product:normal:' . $v['product_id'];
					$this->redis->watch($productKey);

					$this->redis->multi();

					//更新商品的剩余数量
					$this->redis->hIncrBy('product:normal:' . $v['product_id'], 'num', -$v['num']);

					$result = $this->redis->exec();
					if (!$result) {
						throw new \Exception('减少库存失败');
					}

					//orderGood插入一条记录
					$orderGoods[] = [
						'user_id' => $userid,
						'order_id' => $orderId,
						'product_id' => $v['product_id'],
						'product_name' => $productInfo['name'],
						'price' => $productInfo['price'],
						'num' => $v['num'],
						'created_at' => date('Y-m-d H:i:s'),
						'updated_at' => date('Y-m-d H:i:s'),
					];

					//订单总价格叠加
					$priceAll += $productInfo['price'] * $v['num'];

					//把商品数量添加到该数组，用作回滚时还原商品的数量
					array_push($oldNum, $v['num']);
				} catch (\Exception $e) {
					throw $e; // 抛出异常以终止操作
				} finally {
					// 释放锁
					$this->redis->del($lockKey);
				}
			}

			if ($priceAll > $userInfo->balance) {
				throw new \Exception('购买失败，余额不足');
			}

			//扣余额
			$userResult = User::query()->where('id', $userid)->where('token', $token)->update(['balance' => DB::raw('balance - ' . $priceAll)]);
			if (!$userResult) {
				throw new \Exception('扣除余额失败');
			}

			//订单处理
			$this->normalOrder->push([$orderGoods, $orderId, $userid, $priceAll]);

			Db::commit();
			return json_encode(['err' => 0, 'msg' => '购买成功']);
		} catch (Throwable $e) {
			$this->rollbackProductQuantity($orderId, $shopData, $oldNum, 0);
			Db::rollBack();
			return json_encode(['err' => 1, 'msg' => $e->getMessage()]);
		}
	}

	//购买普通商品（压测）（分布式锁）
	public function buyNormalTest($userid, $token, $shopDataJson)
	{
		if (empty($userid) || empty($token)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$oldNum = [];   //各商品的购买数量

		Db::beginTransaction();
		try {
			$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
			if (empty($userInfo)) {
				throw new \Exception('用户不存在');
			}

			if (strtotime($userInfo->tokenExpiration) < time()) {
				throw new \Exception('用户登录过期');
			}

			$priceAll = 0;  //订单总价格
			$orderGoods = []; //订单的商品数组
			foreach ($shopData as $k => $v) {
				$lockKey = 'product_lock:' . $v['product_id'];
				$lockExpire = 5000; // 锁的过期时间，单位毫秒
				$lockAcquired = $this->redis->set($lockKey, 1, ['NX', 'PX' => $lockExpire]);
				if (!$lockAcquired) {
					throw new \Exception('抢购失败，商品id.' . $v['product_id'] . '，为请稍后重试');
				}

				try {
					$isExists = $this->redis->exists('product:normal:' . $v['product_id']);
					if (!$isExists) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在');
					}

					$productInfo = $this->redis->hgetall('product:normal:' . $v['product_id']);
					if (empty($productInfo)) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在了');
					}

					if ($productInfo['is_sale']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '为抢购商品');
					}

					$v['num'] = intval($v['num']);
					if ($v['num'] <= 0) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '数量不大于0');
					}

					if ($productInfo['num'] < $v['num']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，数量不足');
					}

					// 监视商品，如果watch中的值被改变，事务就会终止并回滚
					$productKey = 'product:normal:' . $v['product_id'];
					$this->redis->watch($productKey);

					$this->redis->multi();

					//更新商品的剩余数量
					$this->redis->hIncrBy('product:normal:' . $v['product_id'], 'num', -$v['num']);

					$result = $this->redis->exec();
					if (!$result) {
						throw new \Exception('减少库存失败');
					}

					//orderGood插入一条记录
					$orderGoods[] = [
						'user_id' => $userid,
						'order_id' => $orderId,
						'product_id' => $v['product_id'],
						'product_name' => $productInfo['name'],
						'price' => $productInfo['price'],
						'num' => $v['num'],
						'created_at' => date('Y-m-d H:i:s'),
						'updated_at' => date('Y-m-d H:i:s'),
					];

					//订单总价格叠加
					$priceAll += $productInfo['price'] * $v['num'];

					//把商品数量添加到该数组，用作回滚时还原商品的数量
					array_push($oldNum, $v['num']);
				} catch (\Exception $e) {
					throw $e; // 抛出异常以终止操作
				} finally {
					// 释放锁
					$this->redis->del($lockKey);
				}
			}

			if ($priceAll > $userInfo->balance) {
				throw new \Exception('购买失败，余额不足');
			}

			//扣余额
			$userResult = User::query()->where('id', $userid)->where('token', $token)->update(['balance' => DB::raw('balance - ' . $priceAll)]);
			if (!$userResult) {
				throw new \Exception('扣除余额失败');
			}

			//订单处理
			$this->normalOrder->push([$orderGoods, $orderId, $userid, $priceAll]);

			Db::commit();
			return json_encode(['err' => 0, 'msg' => '购买成功']);
		} catch (Throwable $e) {
			$this->rollbackProductQuantity($orderId, $shopData, $oldNum, 0);
			Db::rollBack();
			return json_encode(['err' => 1, 'msg' => $e->getMessage()]);
		}
	}

	//购买抢购商品，时间限制，限购数量（分布式锁）
	public function buySpike(RequestInterface $request)
	{
		$userid = $request->input('userid');
		$shopDataJson = $request->input('shopData');
		if (empty($userid)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$isAuth = $this->Auth($request, 1);
		$AuthInfo = json_decode($isAuth, true);
		if ($AuthInfo['err'] !== 0) {
			return json_encode(['err' => 1, 'msg' => '认证失败，重新登录']);
		}

		$token = $AuthInfo['token'];
		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$oldNum = [];   //各商品的购买数量

		Db::beginTransaction();
		try {
			$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
			if (empty($userInfo)) {
				throw new \Exception('用户不存在');
			}

			$priceAll = 0;  //订单总价格
			$orderGoods = []; //订单的商品数组
			if (count($shopData) !== 1) {
				throw new \Exception('商品数量错误');
			}

			foreach ($shopData as $k => $v) {
				$lockKey = 'product_lock:' . $v['product_id'];
				$lockExpire = 5000; // 锁的过期时间，单位毫秒
				$lockAcquired = $this->redis->set($lockKey, 1, ['NX', 'PX' => $lockExpire]);
				if (!$lockAcquired) {
					throw new \Exception('抢购失败，商品id.' . $v['product_id'] . '，为请稍后重试');
				}

				try {
					$isExists = $this->redis->exists('product:spike:' . $v['product_id']);
					if (!$isExists) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在');
					}

					$productInfo = $this->redis->hgetall('product:spike:' . $v['product_id']);
					if (empty($productInfo)) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在了');
					}

					if (!$productInfo['is_sale']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '不是抢购商品');
					}

					if (!(strtotime($productInfo['start_time']) < time() && time() < strtotime($productInfo['end_time']))) {
						throw new \Exception('商品id为' . $v['product_id'] . '，不在抢购时间内');
					}

					if ($productInfo['max_buy'] < $v['num']) {
						throw new \Exception('商品id为' . $v['product_id'] . '，限购数量超了');
					}

					$v['num'] = intval($v['num']);
					if ($v['num'] <= 0) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '数量不大于0');
					}

					if ($productInfo['max_buy'] < $v['num']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，限购数量超了');
					}

					if ($productInfo['num'] < $v['num']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，数量不足');
					}

					// 监视商品，如果watch中的值被改变，事务就会终止并回滚
					$productKey = 'product:spike:' . $v['product_id'];
					$this->redis->watch($productKey);

					$this->redis->multi();

					//更新商品的剩余数量
					$this->redis->hIncrBy('product:spike:' . $v['product_id'], 'num', -$v['num']);

					$result = $this->redis->exec();
					if (!$result) {
						throw new \Exception('减少库存失败');
					}

					//orderGood插入一条记录
					$orderGoods[] = [
						'user_id' => $userid,
						'order_id' => $orderId,
						'product_id' => $v['product_id'],
						'product_name' => $productInfo['name'],
						'price' => $productInfo['price'],
						'num' => $v['num'],
						'created_at' => date('Y-m-d H:i:s'),
						'updated_at' => date('Y-m-d H:i:s'),
					];

					//订单总价格叠加
					$priceAll += $productInfo['price'] * $v['num'];

					//把商品数量添加到该数组，用作回滚时还原商品的数量
					array_push($oldNum, $v['num']);
				} catch (\Exception $e) {
					throw $e; // 抛出异常以终止操作
				} finally {
					// 释放锁
					$this->redis->del($lockKey);
				}
			}

			if ($priceAll > $userInfo->balance) {
				throw new \Exception('购买失败，余额不足');
			}

			//扣余额
			$userResult = User::query()->where('id', $userid)->where('token', $token)->update(['balance' => DB::raw('balance - ' . $priceAll)]);
			if (!$userResult) {
				throw new \Exception('扣除余额失败');
			}

			//订单处理
			$this->spikeOrder->push([$orderGoods, $orderId, $userid, $priceAll]);

			Db::commit();
			return json_encode(['err' => 0, 'msg' => '购买成功']);
		} catch (Throwable $e) {
			$this->rollbackProductQuantity($orderId, $shopData, $oldNum, 1);
			Db::rollBack();
			return json_encode(['err' => 1, 'msg' => $e->getMessage()]);
		}
	}

	//购买抢购商品，时间限制，限购数量（压测）（分布式锁）
	public function buySpikeTest($userid, $token, $shopDataJson)
	{
		if (empty($userid) || empty($token)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$oldNum = [];   //各商品的购买数量

		Db::beginTransaction();
		try {
			$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
			if (empty($userInfo)) {
				throw new \Exception('用户不存在');
			}

			if (strtotime($userInfo->tokenExpiration) < time()) {
				throw new \Exception('用户登录过期');
			}

			$priceAll = 0;  //订单总价格
			$orderGoods = []; //订单的商品数组
			if (count($shopData) !== 1) {
				throw new \Exception('商品数量错误');
			}

			foreach ($shopData as $k => $v) {
				$lockKey = 'product_lock:' . $v['product_id'];
				$lockExpire = 5000; // 锁的过期时间，单位毫秒
				$lockAcquired = $this->redis->set($lockKey, 1, ['NX', 'PX' => $lockExpire]);
				if (!$lockAcquired) {
					throw new \Exception('抢购失败，商品id.' . $v['product_id'] . '，为请稍后重试');
				}

				try {
					$isExists = $this->redis->exists('product:spike:' . $v['product_id']);
					if (!$isExists) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在');
					}

					$productInfo = $this->redis->hgetall('product:spike:' . $v['product_id']);
					if (empty($productInfo)) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，不存在了');
					}

					if (!$productInfo['is_sale']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '不是抢购商品');
					}

					if (!(strtotime($productInfo['start_time']) < time() && time() < strtotime($productInfo['end_time']))) {
						throw new \Exception('商品id为' . $v['product_id'] . '，不在抢购时间内');
					}

					if ($productInfo['max_buy'] < $v['num']) {
						throw new \Exception('商品id为' . $v['product_id'] . '，限购数量超了');
					}

					$v['num'] = intval($v['num']);
					if ($v['num'] <= 0) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '数量不大于0');
					}

					if ($productInfo['max_buy'] < $v['num']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，限购数量超了');
					}

					if ($productInfo['num'] < $v['num']) {
						throw new \Exception('购买失败，商品id为' . $v['product_id'] . '，数量不足');
					}

					// 监视商品，如果watch中的值被改变，事务就会终止并回滚
					$productKey = 'product:spike:' . $v['product_id'];
					$this->redis->watch($productKey);

					$this->redis->multi();

					//更新商品的剩余数量
					$this->redis->hIncrBy($productKey, 'num', -$v['num']);

					$result = $this->redis->exec();
					if (!$result) {
						throw new \Exception('减少库存失败');
					}

					//orderGood插入一条记录
					$orderGoods[] = [
						'user_id' => $userid,
						'order_id' => $orderId,
						'product_id' => $v['product_id'],
						'product_name' => $productInfo['name'],
						'price' => $productInfo['price'],
						'num' => $v['num'],
						'created_at' => date('Y-m-d H:i:s'),
						'updated_at' => date('Y-m-d H:i:s'),
					];

					//订单总价格叠加
					$priceAll += $productInfo['price'] * $v['num'];

					//把商品数量添加到该数组，用作回滚时还原商品的数量
					array_push($oldNum, $productInfo['num']);
				} catch (\Exception $e) {
					throw $e; // 抛出异常以终止操作
				} finally {
					// 释放锁
					$this->redis->del($lockKey);
				}
			}

			if ($priceAll > $userInfo->balance) {
				throw new \Exception('购买失败，余额不足');
			}

			//扣余额
			$userResult = User::query()->where('id', $userid)->where('token', $token)->update(['balance' => DB::raw('balance - ' . $priceAll)]);
			if (!$userResult) {
				throw new \Exception('扣除余额失败');
			}

			//订单处理
			$this->spikeOrder->push([$orderGoods, $orderId, $userid, $priceAll]);

			Db::commit();
			return json_encode(['err' => 0, 'msg' => '购买成功']);
		} catch (Throwable $e) {
			$this->rollbackProductQuantity($orderId, $shopData, $oldNum, 1);
			Db::rollBack();
			return json_encode(['err' => 1, 'msg' => $e->getMessage()]);
		}
	}

	//压测买普通商品（分布式锁）
	public function TestGetBuyNormal()
	{
		$userList = $this->TestGetUser();
		$buyFrequency = mt_rand(1, 3);  //购买几个商品
		$shopList = []; //购买商品的数组
		$oldShop = [];
		for ($i = 0; $i < $buyFrequency; $i++) {
			$shopId = $this->TestgetShopIdNormal($oldShop);  //买什么商品
			$buyNum = mt_rand(1, 3);  //这个商品买几件
			array_push($shopList, ['product_id' => $shopId, 'num' => $buyNum]);
			array_push($oldShop, $shopId);
		}
		$this->buyNormalTest($userList['userid'], $userList['token'], json_encode($shopList));
	}

	//压测买抢购商品（分布式锁）
	public function TestGetBuyFlashSale()
	{
		$userList = $this->TestGetUser();
		$buyFrequency = 1;  //购买几个商品
		$shopList = []; //购买商品的数组
		for ($i = 0; $i < $buyFrequency; $i++) {
			$shopId = $this->TestgetShopIdFlashSale();  //买什么商品
			$buyNum = mt_rand(1, 5);  //这个商品买几件
			array_push($shopList, ['product_id' => $shopId, 'num' => $buyNum]);
		}
		$this->buySpikeTest($userList['userid'], $userList['token'], json_encode($shopList));
	}

	//商品回滚
	public function rollbackProductQuantity($orderId, $shopData, $oldNum, $isSale)
	{
		//还原商品的数量
		if ($isSale) {
			$product = 'product:spike:';
		} else {
			$product = 'product:normal:';
		}

		foreach ($oldNum as $k => $v) {
			$this->redis->hIncrBy($product . $shopData[$k]['product_id'], 'num', $v);
		}

		if ($isSale) {
			$this->spikeRollBack->push($orderId);
		} else {
			$this->normalRollBack->push($orderId);
		}
	}

	//购买普通商品（队列）
	public function buyNormalQueue(RequestInterface $request)
	{
		$userid = $request->input('userid');
		$shopDataJson = $request->input('shopData');

		if (empty($userid)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$isAuth = $this->Auth($request, 1);
		$AuthInfo = json_decode($isAuth, true);
		if ($AuthInfo['err'] !== 0) {
			return json_encode(['err' => 1, 'msg' => '认证失败，重新登录']);
		}

		$token = $AuthInfo['token'];
		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
		if (empty($userInfo)) {
			return json_encode(['err' => 1, 'msg' => '用户不存在']);
		}

		foreach ($shopData as $k => $v) {
			$isExists = $this->redis->exists('product:normal:' . $v['product_id']);
			if (!$isExists) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在']);
			}

			$productInfo = $this->redis->hgetall('product:normal:' . $v['product_id']);
			if (empty($productInfo)) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在了']);
			}

			if ($productInfo['is_sale']) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '为抢购商品']);
			}

			$v['num'] = intval($v['num']);
			if ($v['num'] <= 0) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '数量不大于0']);
			}
		}

		$res = $this->normalBuy->push([$shopDataJson, $orderId, $userid]);
		if ($res) {
			$data['err'] = 0;
			$data['msg'] = 'pro发送成功';
		} else {
			$data['err'] = 1;
			$data['msg'] = 'pro发送失败';
		}
		return json_encode($data);
	}

	//购买普通商品（压测）（队列）	
	public function buyNormalTestQueue($userid, $token, $shopDataJson)
	{
		if (empty($userid) || empty($token)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
		if (empty($userInfo)) {
			return json_encode(['err' => 1, 'msg' => '用户不存在']);
		}

		if (strtotime($userInfo->tokenExpiration) < time()) {
			return json_encode(['err' => 1, 'msg' => '用户登录过期']);
		}

		foreach ($shopData as $k => $v) {
			$isExists = $this->redis->exists('product:normal:' . $v['product_id']);
			if (!$isExists) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在']);
			}

			$productInfo = $this->redis->hgetall('product:normal:' . $v['product_id']);
			if (empty($productInfo)) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在了']);
			}

			if ($productInfo['is_sale']) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '为抢购商品']);
			}

			$v['num'] = intval($v['num']);
			if ($v['num'] <= 0) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '数量不大于0']);
			}
		}

		$res = $this->normalBuy->push([$shopDataJson, $orderId, $userid]);
		if ($res) {
			$data['err'] = 0;
			$data['msg'] = 'pro发送成功';
		} else {
			$data['err'] = 1;
			$data['msg'] = 'pro发送失败';
		}
		return json_encode($data);
	}

	//购买抢购商品，时间限制，限购数量（队列）
	public function buySpikeQueue(RequestInterface $request)
	{
		$userid = $request->input('userid');
		$shopDataJson = $request->input('shopData');
		if (empty($userid)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$isAuth = $this->Auth($request, 1);
		$AuthInfo = json_decode($isAuth, true);
		if ($AuthInfo['err'] !== 0) {
			return json_encode(['err' => 1, 'msg' => '认证失败，重新登录']);
		}

		$token = $AuthInfo['token'];
		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
		if (empty($userInfo)) {
			return json_encode(['err' => 1, 'msg' => '用户不存在']);
		}

		if (count($shopData) !== 1) {
			return json_encode(['err' => 1, 'msg' => '商品数量错误']);
		}

		foreach ($shopData as $k => $v) {
			$isExists = $this->redis->exists('product:spike:' . $v['product_id']);
			if (!$isExists) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在']);
			}

			$productInfo = $this->redis->hgetall('product:spike:' . $v['product_id']);
			if (empty($productInfo)) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在了']);
			}

			if (!$productInfo['is_sale']) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '不是抢购商品']);
			}

			$v['num'] = intval($v['num']);
			if ($v['num'] <= 0) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '数量不大于0']);
			}

			if (!(strtotime($productInfo['start_time']) < time() && time() < strtotime($productInfo['end_time']))) {
				return json_encode(['err' => 1, 'msg' => '商品id为' . $v['product_id'] . '，不在抢购时间内']);
			}

			if ($productInfo['max_buy'] < $v['num']) {
				return json_encode(['err' => 1, 'msg' => '商品id为' . $v['product_id'] . '，限购数量超了']);
			}
		}

		$res = $this->spikeBuy->push([$shopDataJson, $orderId, $userid]);
		if ($res) {
			$data['err'] = 0;
			$data['msg'] = 'pro发送成功';
		} else {
			$data['err'] = 1;
			$data['msg'] = 'pro发送失败';
		}
		return json_encode($data);
	}

	//购买抢购商品，时间限制，限购数量（压测）（队列）
	public function buySpikeTestQueue($userid, $token, $shopDataJson)
	{
		if (empty($userid) || empty($token)) {
			return json_encode(['err' => 1, 'msg' => '缺少用户信息']);
		}

		if (empty($shopDataJson)) {
			return json_encode(['err' => 1, 'msg' => '缺少商品信息']);
		}

		$orderId = $this->generateOrderNumber();
		$shopData = json_decode($shopDataJson, true);
		$userInfo = User::query()->where('id', $userid)->where('token', $token)->lockForUpdate()->first();
		if (empty($userInfo)) {
			return json_encode(['err' => 1, 'msg' => '用户不存在']);
		}

		if (strtotime($userInfo->tokenExpiration) < time()) {
			return json_encode(['err' => 1, 'msg' => '用户登录过期']);
		}

		if (count($shopData) !== 1) {
			return json_encode(['err' => 1, 'msg' => '商品数量错误']);
		}

		foreach ($shopData as $k => $v) {
			$isExists = $this->redis->exists('product:spike:' . $v['product_id']);
			if (!$isExists) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在']);
			}

			$productInfo = $this->redis->hgetall('product:spike:' . $v['product_id']);
			if (empty($productInfo)) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '，不存在了']);
			}

			if (!$productInfo['is_sale']) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '不是抢购商品']);
			}

			$v['num'] = intval($v['num']);
			if ($v['num'] <= 0) {
				return json_encode(['err' => 1, 'msg' => '购买失败，商品id为' . $v['product_id'] . '数量不大于0']);
			}

			if (!(strtotime($productInfo['start_time']) < time() && time() < strtotime($productInfo['end_time']))) {
				return json_encode(['err' => 1, 'msg' => '商品id为' . $v['product_id'] . '，不在抢购时间内']);
			}

			if ($productInfo['max_buy'] < $v['num']) {
				return json_encode(['err' => 1, 'msg' => '商品id为' . $v['product_id'] . '，限购数量超了']);
			}
		}

		$res = $this->spikeBuy->push([$shopDataJson, $orderId, $userid]);
		if ($res) {
			$data['err'] = 0;
			$data['msg'] = 'pro发送成功';
		} else {
			$data['err'] = 1;
			$data['msg'] = 'pro发送失败';
		}
		return json_encode($data);
	}

	//压测买普通商品（队列）
	public function TestGetBuyNormalQueue()
	{
		$userList = $this->TestGetUser();
		$buyFrequency = mt_rand(1, 3);  //购买几个商品
		$shopList = []; //购买商品的数组
		$oldShop = [];
		for ($i = 0; $i < $buyFrequency; $i++) {
			$shopId = $this->TestgetShopIdNormal($oldShop);  //买什么商品
			$buyNum = mt_rand(1, 3);  //这个商品买几件
			array_push($shopList, ['product_id' => $shopId, 'num' => $buyNum]);
			array_push($oldShop, $shopId);
		}
		$this->buyNormalTestQueue($userList['userid'], $userList['token'], json_encode($shopList));
	}

	//压测买抢购商品（队列）
	public function TestGetBuyFlashSaleQueue()
	{
		$userList = $this->TestGetUser();
		$buyFrequency = 1;  //购买几个商品
		$shopList = []; //购买商品的数组
		for ($i = 0; $i < $buyFrequency; $i++) {
			$shopId = $this->TestgetShopIdFlashSale();  //买什么商品
			$buyNum = mt_rand(1, 5);  //这个商品买几件
			array_push($shopList, ['product_id' => $shopId, 'num' => $buyNum]);
		}
		$this->buySpikeTestQueue($userList['userid'], $userList['token'], json_encode($shopList));
	}

	//生成订单号
	public function generateOrderNumber()
	{
		$orderNum = $this->redis->incr('orderNum');
		$prefix = 'ORD';
		$orderId = $prefix . (10000000 + $orderNum);
		return $orderId;
	}

	//获取随机用户
	public function TestGetUser()
	{
		$userList = [
			["userid" => "1", "token" => "39b92c0d6cce85ed950213797946cf29a1a9d1530629f40b031af208e5a02714"],
			["userid" => "2", "token" => "8ce28bb2aafa9448500ddbdcda478f8aa729f9d345c903a553477a9c4314828b"],
			["userid" => "3", "token" => "9e4ce3c386886f83a1b569c3b66dd5389b1bccaab713e37057dd092065555fc9"],
			["userid" => "4", "token" => "82034c4caca4afa23a42bb4fb04e4dbf9bdaf143f64026ed7050df3e0f795be5"],
			["userid" => "5", "token" => "6450734dc466e99ab1d74c9fbb10e91563f5abac07089813a37c692b3518eb81"],
			["userid" => "6", "token" => "ed121d749bd7851f20c3a2bdba3f77e3016ee6c411546cce7d3040b886234fe6"],
			["userid" => "7", "token" => "b16d09f3a01d69d6895009bd1618cff18851d60076012cc772a1115d252de0e1"],
			["userid" => "8", "token" => "785c43c4e0ffa3e23fe2bef762ddc808418bcb843c9154adb8dd9c212c6bb552"],
			["userid" => "9", "token" => "78172078a207a391b82408e714338f26d5e61e784a5aa97065f1622695d9b0a3"],
			["userid" => "10", "token" => "6f1a7b75926f958e4e70bd8fbb8fa5a5e694d62935b01737a604f23da870a476"],
			["userid" => "11", "token" => "ddf6305415e70aa192a16521c12d0544ede5b01942a8099470b9ecab21479a07"],
			["userid" => "12", "token" => "427dd404e67dc3a8833dbe69047bf9cb5530d305ca233aaeed5fa1a5fe33dd73"],
			["userid" => "13", "token" => "b5e4d0f525959552ee24d6ebb390f475cdf0f9d5fec0479e0385ac7cacf9e045"],
			["userid" => "14", "token" => "5b5e3c972f8742095993f68345d8e0c2288296bfe16133b841cf905bbc742f5e"],
			["userid" => "15", "token" => "d5ea2795be6ab14180c333f9365a756302f790aa824726e6c1c13a6b9a8a84ed"],
			["userid" => "16", "token" => "f8c625a25751cda112e4df6db84b7008ccbeb5540c23b1616aa7e3ccb4fb1e73"],
			["userid" => "17", "token" => "4f12763bbb1d0dff3c66bd95b456c8c0a19ab5ddd82a0c5c8f02a5a4427281e1"],
			["userid" => "18", "token" => "030cc60e7727953fb2eb6816af5b8e9d8ecf25120d078ed1ba3d1ace3b17a94c"],
			["userid" => "19", "token" => "d58beee6523bb8cc1416ab3a1ef3c3e97d143d397cde63a3715108b3a3eecb9e"],
			["userid" => "20", "token" => "57d95aaefedb37fd2245413d731323560b0b8878de18f8e4ac56190b1f3c0fe1"],
		];
		$randomKey = array_rand($userList);
		$randomUser = $userList[$randomKey];
		return $randomUser;
	}

	//获取随机普通商品id
	public function TestgetShopIdNormal($oldShop)
	{
		$shopList = [29, 30, 31];
		$shopList = array_diff($shopList, $oldShop);
		$randomIndex = array_rand($shopList);
		$randomShop = $shopList[$randomIndex];
		return $randomShop;
	}

	//获取随机抢购商品id
	public function TestgetShopIdFlashSale()
	{
		$shopList = [34, 35];
		$randomIndex = array_rand($shopList);
		$randomShop = $shopList[$randomIndex];
		return $randomShop;
	}

	//发送异步消息
	public function sendA()
	{
		$this->normalOrder->push([
			'group@hyperf.ioAAA',
			'https://doc.hyperf.ioAAA',
			'https://www.hyperf.ioAAA',
		]);
		return 'successAAA';
	}

	public function sendB()
	{
		$this->normalRollBack->push([
			'group@hyperf.ioBBB',
			'https://doc.hyperf.ioBBB',
			'https://www.hyperf.ioBBB',
		]);

		return 'successBBB';
	}

	public function sendC()
	{
		$this->spikeOrder->push("ccc");

		return 'successCCC';
	}

	public function sendD()
	{
		$this->spikeRollBack->push([
			'group@hyperf.ioDDD',
			'https://doc.hyperf.ioDDD',
			'https://www.hyperf.ioDDD',
		]);

		return 'successDDD';
	}
}
